home *** CD-ROM | disk | FTP | other *** search
Wrap
/* handlers.c -- AppleEvent Handlers for MANDELBROT UNIX daemon. */ /* %F% %I% */ /* * Copyright 1993 Apple Computer, Inc. * All Rights Reserved. * * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF APPLE COMPUTER, INC. * The copyright notice above does not evidence any actual or * intended publication of such source code. */ /* * 9502.16 jkc Added offset to FillMandel() to reduce r*rows calcs * 9502.17 jkc Added new globals to reduce and count math operations. * Replaced ColToRe() and RowToIm() with macros. Reduced * quantity and improved quality of debug strings. */ #include <stdio.h> #include <sys/select.h> #include <sys/statfs.h> #include <fcntl.h> #include <sys/types.h> #include <math.h> #include "Types.h" #include "AppleEvents.h" #include "AERegistry.h" #include "AUXAESuite.h" #include "mandel.h" typedef unsigned char BOOLEAN; #define UNAME "/usr/bin/uname -vr 2>&1" #define FREE(p) if (p != NULL) free(p); char *strcmp(); char *strchr(); char *strtok(); extern char *databuf; extern int errno; /* fd_set opensocks; /* */ /* char type[4]; /* */ /* char creator[4]; /* */ char errorStr[1024]; extern int sessionid; extern boolean pending_cmd;; extern boolean sendconfig; extern char OSVersion[32]; extern char *serverVersion; extern char *clientVersion; extern boolean TimeToQuit; extern time_t time_of_last_recv; /* last time we recvd a heartbeat */ extern FILE *debugfp; extern void do_filesystem(); extern struct FS_List *FS_list; extern int theInterval; OSErr HandleNullEvent (msg, reply, refcon) /* -JSM- */ AppleEvent *msg; AppleEvent *reply; long refcon; { int result; DescType returnedType; Size returnedSize; #ifdef DEBUG fprintf(debugfp, ">>>HandleNullEvent()\n"); #endif if (sessionid == 0) AEGetParamPtr(msg,keySessionID,typeInteger,&returnedType,(Ptr)&sessionid,sizeof(sessionid),&returnedSize); #ifdef DEBUG fprintf(debugfp, "sessionid = (%d)\n", sessionid); #endif strcpy(errorStr,"S Success.\n"); errorStr[1]='\0'; #ifdef DEBUG fprintf(debugfp, "errorStr = (%s)\n", errorStr); fprintf(debugfp, "errorStr+2 = (%s)\n", errorStr+2); #endif result=AEPutParamPtr(reply,keyErrorNumber,typeChar,errorStr,strlen(errorStr)); result=AEPutParamPtr(reply,keyErrorString,typeChar,errorStr+2,strlen(errorStr+2)); return (noErr); } OSErr HandleQuit (msg, reply, refcon) /* -JSM- */ AppleEvent *msg; AppleEvent *reply; long refcon; { int result; DescType returnedType; Size returnedSize; #ifdef DEBUG fprintf(debugfp, ">>>HandleQuit()\n"); #endif TimeToQuit=TRUE; /* Time to die... */ return (noErr); } OSErr HandleHeartBeat (msg, reply, refcon) /* -JSM- */ AppleEvent *msg; AppleEvent *reply; long refcon; { int result; DescType returnedType; Size returnedSize; #ifdef DEBUG fprintf(debugfp, ">>>HandleHeartBeat()\n"); #endif (void)time(&time_of_last_recv); return (noErr); } OSErr HandleVersionEvent (msg, reply, refcon) /* -JSM- */ AppleEvent *msg; AppleEvent *reply; long refcon; { DescType returnedType; Size returnedSize; char *p, *clientMajor, *serverMajor; char tmpdata[1024]; char *tmpbuf; char *version; char *level; FILE *fp; int failcnt=0; int num; int result; OSErr retval; #ifdef DEBUG fprintf(debugfp, ">>>HandleVersionEvent()\n"); #endif retval=AEGetParamPtr(msg, keyAEVersion, typeChar, &returnedType, (Ptr)databuf, DATABUFSIZE-1, &returnedSize); databuf[returnedSize] = '\0'; if (retval) { strcpy(errorStr,"F Required parameter (keyAEVersion) not found!\n"); } else { clientVersion = (char *)malloc(1+strlen(databuf)); strcpy(clientVersion,databuf); if (strcmp(clientVersion,serverVersion) != 0) { /* if versions are not same, look closer */ clientMajor = (char *)malloc(1+strlen(clientVersion)); serverMajor = (char *)malloc(1+strlen(serverVersion)); strcpy(clientMajor,clientVersion); p = strchr(clientMajor,'.'); if (p != NULL) *p = '\0'; strcpy(serverMajor,serverVersion); p = strchr(serverMajor,'.'); if (p != NULL) *p = '\0'; if (strcmp(clientVersion,serverVersion) != 0) { /* if major versions numbers are not same... */ TimeToQuit=TRUE; /* Set global shutdown flag to shutdown server */ errorStr[0] = 'F'; strcpy(errorStr+2,serverVersion); } else { errorStr[0] = 'S'; strcpy(errorStr+2,serverVersion); } FREE(clientMajor); FREE(serverMajor); } else { errorStr[0] = 'S'; strcpy(errorStr+2,serverVersion); } } if (errorStr[0] == 'S') { sendconfig = TRUE; failcnt=0; uname: if ((fp=popen(UNAME,"r")) == NULL) { #ifdef DEBUG fprintf(debugfp,"popen() failed on command (%s)\n",UNAME); fflush(debugfp); #endif return(-1); } tmpbuf = (char *)mymalloc(1024); *tmpbuf = '\0'; while ((num=read(fileno(fp),tmpdata,sizeof(tmpdata))) > 0) { tmpbuf = strncat(tmpbuf,tmpdata,num); } retval=pclose(fp); if (retval) { #ifdef DEBUG fprintf(debugfp,"pclose() indicates a failure from %s\n",UNAME); fprintf(debugfp,"command returned: %s\n",tmpbuf); fflush(debugfp); #endif if (failcnt < 3) { failcnt++; sleep(1); goto uname; } else { #ifdef DEBUG fprintf(debugfp,"Too many failures!\n"); fflush(debugfp); #endif errorStr[0] = 'F'; strcpy(errorStr+2,"\n"); strcpy(OSVersion,"0.0"); } } else { if (tmpbuf[0] != '\0') { level=strtok(tmpbuf," \n"); #ifdef DEBUG fprintf(debugfp,"level = (%s)\n",level); fflush(debugfp); #endif version=strtok((char *)NULL," \n"); #ifdef DEBUG fprintf(debugfp,"version = (%s)\n",version); fflush(debugfp); #endif strcpy(OSVersion,version); #ifdef DEBUG fprintf(debugfp,"CP1\n"); fflush(debugfp); #endif strcat(OSVersion,"."); #ifdef DEBUG fprintf(debugfp,"CP1\n"); fflush(debugfp); #endif strcat(OSVersion,level); #ifdef DEBUG fprintf(debugfp, "OSVersion = (%s)\n", OSVersion); fflush(debugfp); #endif } FREE(tmpbuf); } } errorStr[1] = '\0'; #ifdef DEBUG fprintf(debugfp, "errorStr = (%s)\n", errorStr); fprintf(debugfp, "errorStr+2 = (%s)\n", errorStr+2); fprintf(debugfp, "OSVersion = (%s)\n", OSVersion); fflush(debugfp); #endif result=AEPutParamPtr(reply,keyErrorNumber,typeChar,errorStr,strlen(errorStr)); result=AEPutParamPtr(reply,keyErrorString,typeChar,errorStr+2,strlen(errorStr+2)); result=AEPutParamPtr(reply,keyAEVersion,typeChar,OSVersion,strlen(OSVersion)); return (noErr); } OSErr HandleInterval (msg, reply, refcon) /* -JSM- */ AppleEvent *msg; AppleEvent *reply; long refcon; { DescType returnedType; Size returnedSize; int exitstatus, num, result; int interval; char tmpdata[1024]; FILE *fp; OSErr retval; #ifdef DEBUG fprintf(debugfp, ">>>HandleInterval()\n"); #endif retval=AEGetParamPtr (msg, keyInterval, typeInteger, &returnedType, &interval, sizeof(interval), &returnedSize); if (retval) { strcpy(errorStr,"F Required parameter (keyAEInteger) not found!\n"); } else { theInterval = interval; strcpy(errorStr,"S Success.\n"); } errorStr[1]='\0'; #ifdef DEBUG fprintf(debugfp, "errorStr = (%s)\n", errorStr); fprintf(debugfp, "errorStr+2 = (%s)\n", errorStr+2); #endif result=AEPutParamPtr(reply,keyErrorNumber,typeChar,errorStr,strlen(errorStr)); result=AEPutParamPtr(reply,keyErrorString,typeChar,errorStr+2,strlen(errorStr+2)); if (retval) return(retval); else return(noErr); } /* AE Mandelbrot server, version 2 with good divide-and-conquer technique */ /* 5 Feb 92 by Mark Maxham Apple ATG/SysSoft */ /* (c) 1992 Apple Computer Inc. */ extern char type[]; extern char creator[]; /* globals for the divide-n-conquer routine */ double rmax, rmin, imax, imin, ipercol, rperrow; long rows, cols, maxiter; unsigned char* bytebuf; #ifdef MDEBUG long ctrcnt, rticnt; /* Count calls to ColToRe() and RowToIm() */ long itercnt, mndlcnt; /* Count calls to mandelbrot() and total iterations */ long mostiter; /* Largest number of iterations used */ long boxcnt; /* Count iterations of box optimization loops */ #endif unsigned char mandelbrot(c_r, c_i) double c_r, c_i; { double z_r = 0, z_i = 0, z_rs, z_is; long iter = 0; #ifdef MDEBUG mndlcnt++; #endif /* while (iter < 255 && |Z| < 2) (hard coding of '2' bad, FIXME) */ while (iter < maxiter && ((z_rs=z_r*z_r) + (z_is=z_i*z_i)) < 4) { z_i = 2*z_r*z_i + c_i; z_r = z_rs - z_is + c_r; iter++; #ifdef MDEBUG itercnt++; #endif } #ifdef MDEBUG if (iter > mostiter) mostiter = iter; #endif return (unsigned char) iter; } /* globals for the divide-n-conquer routine used to be here */ #define RowToIm(row) (double)(row * ipercol + imin) #define ColToRe(col) (double)(col * rperrow + rmin) /* double RowToIm(row) int row; { #ifdef MDEBUG rticnt++; #endif return row * ipercol + imin; } double ColToRe(col) int col; { #ifdef MDEBUG ctrcnt++; #endif return col * rperrow + rmin; } */ void FillMandel(r1, c1, r2, c2) int r1; int r2; int c1; int c2; { unsigned char origval, val; int r, c, offset; BOOLEAN same; double re, im; /* I think this is a valid base case for the recursion ... */ if (r1 >= r2 || c1 >= c2) return; val = origval = mandelbrot(ColToRe(c1), RowToIm(r1)); same = true; /* box optimization: top */ r = r1; im = RowToIm(r); offset = r*rows; for (c = c1; c <= c2; c++) { val = bytebuf[c + offset]; if (val == 0) { re = ColToRe(c); val = bytebuf[c + offset] = mandelbrot(re, im); } if (same && (val != origval)) same = false; #ifdef MDEBUG boxcnt++; #endif } /* box optimization: bottom */ r = r2; im = RowToIm(r); offset = r*rows; for (c = c1; c <= c2; c++) { val = bytebuf[c + offset]; if (val == 0) { re = ColToRe(c); val = bytebuf[c + offset] = mandelbrot(re, im); } if (same && (val != origval)) same = false; #ifdef MDEBUG boxcnt++; #endif } /* box optimization: left */ c = c1; re = ColToRe(c); for (r = r1; r <= r2; r++) { offset = r*rows; val = bytebuf[c + offset]; if (val == 0) { im = RowToIm(r); val = bytebuf[c + offset] = mandelbrot(re, im); } if (same && (val != origval)) same = false; #ifdef MDEBUG boxcnt++; #endif } /* box optimization: right */ c = c2; re = ColToRe(c); for (r = r1; r <= r2; r++) { offset = r*rows; val = bytebuf[c + offset]; if (val == 0) { im = RowToIm(r); val = bytebuf[c + offset] = mandelbrot(re, im); } if (same && (val != origval)) same = false; #ifdef MDEBUG boxcnt++; #endif } /* ah, the joys of recursion */ if (same) { /* All box edges have same val, so assume every point has same value */ for (r = r1+1; r <= r2-1; r++) { offset = r*rows; for (c = c1+1; c <= c2-1; c++) bytebuf[c + offset] = val; } } else { /* Subdivide box and try again */ if (r2-r1 > c2-c1) { FillMandel(r1, c1, (r1+r2)/2, c2); FillMandel((r1+r2)/2 + 1, c1, r2, c2); } else { FillMandel(r1, c1, r2, (c1+c2)/2); FillMandel(r1, (c1+c2)/2 + 1, r2, c2); } } } /* FillMandel() */ OSErr HandleMandel(msg, reply, refcon) AppleEvent* msg; AppleEvent* reply; long refcon; { int i, j; long rown, coln, newiter; long servid, docid, transid; double mag; DescType rt; size_t rs; #ifdef DEBUG long starttime, endtime; fprintf(debugfp, ">>>HandleMandel()\n"); fflush(debugfp); #endif AEGetParamPtr(msg, 'rows', 'long', &rt, &rows, sizeof(rows), &rs); AEGetParamPtr(msg, 'cols', 'long', &rt, &cols, sizeof(cols), &rs); AEGetParamPtr(msg, 'col#', 'long', &rt, &coln, sizeof(coln), &rs); AEGetParamPtr(msg, 'row#', 'long', &rt, &rown, sizeof(rown), &rs); AEGetParamPtr(msg, 'trx#', 'long', &rt, &transid, sizeof(transid), &rs); AEGetParamPtr(msg, 'doc#', 'long', &rt, &docid, sizeof(docid), &rs); AEGetParamPtr(msg, 'srv#', 'long', &rt, &servid, sizeof(servid), &rs); AEGetParamPtr(msg, 'imin', 'doub', &rt, &imin, sizeof(imin), &rs); AEGetParamPtr(msg, 'imax', 'doub', &rt, &imax, sizeof(imax), &rs); AEGetParamPtr(msg, 'rmin', 'doub', &rt, &rmin, sizeof(rmin), &rs); AEGetParamPtr(msg, 'rmax', 'doub', &rt, &rmax, sizeof(rmax), &rs); errno = 0; maxiter = 256*3-1; mag = (double)cols / (rmax - rmin); newiter = 256 * (3 + (int)log(pow(mag, 4))) - 1; #ifdef DEBUG if (errno != 0) fprintf(debugfp, "D'Oh! Math error occurred, %d\n", errno); #endif /* maxiter = newiter; */ #ifdef MDEBUG mostiter = 0; fprintf(debugfp,"[%d] Calculating %dx%d grid for [%d,%d] from (%.12g,%.12g) to (%.12g,%.12g) with resolution of %d\n", transid, cols, rows, coln, rown, rmin, imin, rmax, imax, maxiter); fprintf(debugfp,"[%d] [%d, %d] ", transid, coln, rown); fprintf(debugfp,"mag = %g, newiter = %d\n", mag, newiter); fflush(debugfp); #endif AEPutParamPtr(reply, 'row#', 'long', &rown, sizeof(rown)); AEPutParamPtr(reply, 'col#', 'long', &coln, sizeof(coln)); AEPutParamPtr(reply, 'trx#', 'long', &transid, sizeof(transid)); AEPutParamPtr(reply, 'doc#', 'long', &docid, sizeof(docid)); AEPutParamPtr(reply, 'srv#', 'long', &servid, sizeof(servid)); bytebuf = (unsigned char*) malloc(rows * cols * sizeof(unsigned char)); if (!bytebuf) { #ifdef DEBUG fprintf(debugfp,"Panic! malloc failure of bytebuf in mandel.c\n"); fflush(debugfp); #endif } ipercol = (imax - imin) / cols; rperrow = (rmax - rmin) / rows; for (i=0; i < rows*cols; i++) bytebuf[i] = '\0'; #ifdef MDEBUG /* Initialize operation counters and timer */ ctrcnt = rticnt = itercnt = mndlcnt = boxcnt = 0; starttime = clock(); #endif FillMandel(0, 0, rows-1, cols-1); #ifdef MDEBUG /* Report operation counters and exec time */ endtime = clock(); fprintf(debugfp, "ColToRe() calls: %d RowToIm() calls: %d", ctrcnt, rticnt); fprintf(debugfp, " mandelbrot() calls: %d total iterations: %d", mndlcnt, itercnt); fprintf(debugfp, " Box optimization loops: %d\n", boxcnt); fprintf(debugfp, "irange = %.12g, rrange = %.12g ", (imax-imin), (rmax-rmin)); fprintf(debugfp, "Most iterations: %d\n", mostiter); fprintf(debugfp, "CPU time: %d\n", endtime-starttime); fflush(debugfp); #endif #ifdef MDEBUG if (newiter >= 37000) { for (i=0;i<10;i++) fprintf(debugfp, "bytebuf[%d] = %d\n",i,bytebuf[i]); fflush(debugfp); } #endif AEPutParamPtr(reply, 'data', 'TEXT', bytebuf, (size_t) rows*cols); free(bytebuf); #ifdef DEBUG fprintf(debugfp,"responding... "); fprintf(debugfp,"done\n"); fflush(debugfp); #endif return(noErr); }